package com.clothing.utils;

import java.io.IOException;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.PBEParameterSpec;

import org.apache.log4j.Logger;

/**
 * @ClassName: Encrypt
 * @Description: TODO(DES加解密工具类)
 * @author Administrator
 * @date 2011-12-28 下午10:35:23
 * @version 1.0
 */
public class DESUtils
{
    private static Logger logger = Logger.getLogger(DESUtils.class);

    // 生成密钥时的使用的密码
    private final static String PASSWORD = "UbiCloud Tech";

    // 生成密钥时的使用的salt
    private final static String SALT = "Mode APP";

    // 生成密钥时的迭代次数
    public final static int COUNT = 16;

    /**
     * name of the character set to use for converting between characters and
     * bytes
     */
    private static final String CHARSET_NAME = "UTF-8";

    /**
     * @Title: randomEncode
     * @Description: TODO(随机加密)
     * @param @param info
     * @param @return 设定文件
     * @return String 返回类型
     * @throws
     */
    public static String randomEncode(String info)
    {
        if (info == null)
        {
            return null;
        }

        String current = Long.toHexString(System.currentTimeMillis());
        int length = current.length();
        String salt = current.substring(length - 8, length).toUpperCase();
        String count = Integer.toHexString((int) ((Math.random() * 15) + 1))
                .toUpperCase();

        Cipher pbeCipher = getCipher(Cipher.ENCRYPT_MODE, count, salt);

        if (null == pbeCipher)
        {
            return null;
        }

        try
        {
            // 明文
            byte[] cleartext = info.getBytes(CHARSET_NAME);

            // 加密
            byte[] ciphertext = pbeCipher.doFinal(cleartext);

            // 返回十六进制字符串密文

            String oneEnStr = bytes2HexString(ciphertext) + count + salt;

            return desEncode(oneEnStr);
        }
        catch(Exception e)
        {
            logger.error("DES encode error", e);
            return null;
        }
    }

    /**
     * @Title: desEncode
     * @Description: TODO(DES加密)
     * @param @param info
     * @param @return 设定文件
     * @return String 返回类型
     * @throws
     */
    public static String desEncode(String info)
    {

        if (info == null)
        {
            return null;
        }

        Cipher pbeCipher = getCipher(Cipher.ENCRYPT_MODE);

        if (null == pbeCipher)
        {
            return null;
        }

        try
        {
            // 明文
            byte[] cleartext = info.getBytes(CHARSET_NAME);

            // 加密
            byte[] ciphertext = pbeCipher.doFinal(cleartext);

            // 返回十六进制字符串密文
            return bytes2HexString(ciphertext);
        }
        catch(Exception e)
        {
            logger.error("DES encode error", e);
            return null;
        }

    }

    /**
     * @Title: desDecode
     * @Description: TODO(DES解密)
     * @param info
     *            十六进制字符串
     * @return String 返回类型
     * @throws
     */
    public static String desDecode(String info)
    {
        return desDecode(info, null, null);
    }

    /**
     * @Title: desDecode
     * @Description: TODO(DES解密)
     * @param @param info
     * @param @param count
     * @param @param salt
     * @param @return 设定文件
     * @return String 返回类型
     * @throws
     */
    public static String desDecode(String info, String count, String salt)
    {
        if (info == null)
        {
            return null;
        }

        Cipher pbeCipher = getCipher(Cipher.DECRYPT_MODE, count, salt);

        if (null == pbeCipher)
        {
            return null;
        }

        try
        {
            // 密文
            byte[] ciphertext = hex2byte(info);

            // 解密
            byte[] cleartext = pbeCipher.doFinal(ciphertext);

            // 返回明文
            return new String(cleartext, CHARSET_NAME);
        }
        catch(Exception e)
        {
            logger.error("DES decode error", e);
            return null;
        }
    }

    /**
     * @Title: randomDecode
     * @Description: TODO(随机解密)
     * @param @param info
     * @param @return 设定文件
     * @return String 返回类型
     * @throws
     */
    public static String randomDecode(String info)
    {
        if (info == null)
        {
            return null;
        }

        Cipher pbeCipher = getCipher(Cipher.DECRYPT_MODE);

        if (null == pbeCipher)
        {
            return null;
        }

        try
        {
            // 密文
            byte[] ciphertext = hex2byte(info);

            // 解密
            byte[] cleartext = pbeCipher.doFinal(ciphertext);

            // 明文
            String result = new String(cleartext, CHARSET_NAME);

            int length = result.length();

            String salt = result.substring(length - 8, length);
            String count = result.substring(length - 9, length - 8);
            result = result.substring(0, length - 9);

            return desDecode(result, count, salt);

        }
        catch(Exception e)
        {
            logger.error("DES decode error", e);
            return null;
        }
    }

    private static Cipher getCipher(int mode, String count, String salt)
    {
        try
        {
            PBEKeySpec pbeKeySpec = new PBEKeySpec(PASSWORD.toCharArray());
            SecretKeyFactory keyFac = SecretKeyFactory
                    .getInstance("PBEWithMD5AndDES");
            SecretKey pbeKey = keyFac.generateSecret(pbeKeySpec);

            if (null == salt)
            {
                salt = SALT;
            }

            // 生成pbe算法所需的参数对象，两个参数详见 RSA的 PKCS #5 标准
            PBEParameterSpec pbeParamSpec = new PBEParameterSpec(
                    salt.getBytes(CHARSET_NAME), null == count ? COUNT
                            : Integer.parseInt(count, 16));

            // 生成一个加密器
            Cipher pbeCipher = Cipher.getInstance("PBEWithMD5AndDES");

            // 初始化加密器
            pbeCipher.init(mode, pbeKey, pbeParamSpec);

            return pbeCipher;
        }
        catch(Exception e)
        {
            logger.error("Get cipher error", e);
            return null;
        }
    }

    private static Cipher getCipher(int mode)
    {
        return getCipher(mode, null, null);
    }

    public static byte[] hex2byte(String str)
    {
        if (str == null)
            return null;
        str = str.trim();
        int len = str.length();
        if (len == 0 || len % 2 == 1)
            return null;
        byte[] b = new byte[len / 2];
        try
        {
            for (int i = 0; i < str.length(); i += 2)
            {
                b[i / 2] = (byte) Integer
                        .decode("0x" + str.substring(i, i + 2)).intValue();
            }
            return b;
        }
        catch(Exception e)
        {
            return null;
        }
    }

    public static String bytes2HexString(byte[] b)
    {
        String ret = "";
        for (int i = 0; i < b.length; i++)
        {
            String hex = Integer.toHexString(b[i] & 0xFF);
            if (hex.length() == 1)
            {
                hex = '0' + hex;
            }

            ret += hex.toUpperCase();
        }
        return ret;
    }

    public static void main(String[] args) throws IOException
    {
        String str = DESUtils.desEncode("1:111111");

        System.out.println(str);

        System.out.println(DESUtils.desDecode(str));

        String randomStr = DESUtils.randomEncode("1:111111");

        System.out.println(randomStr);

        System.out.println(DESUtils.randomDecode(randomStr));

    }
}
